home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / oobpls10.zip / OFLGIF.PAS < prev    next >
Pascal/Delphi Source File  |  1992-11-06  |  9KB  |  368 lines

  1. {$F+,O+,T-,X+}
  2. unit OfLGIF;   {simple offline GIF decoder}
  3.  
  4. {.$DEFINE Debug}
  5.  
  6. interface
  7.  
  8. uses
  9.   DOS,
  10.   OpInline,
  11.   OpRoot,
  12.   OpCrt,
  13.   OpMouse,
  14.   OpDrag,
  15.   OpString,
  16.   DeGIF,
  17.   GIFVideo;
  18.  
  19.  
  20. const
  21.   UnitVers = '1.0d';
  22.   UnitDate = '05-Jun-91';
  23.  
  24. function DisplayGIFOffLine(FN : String) : Boolean;
  25.  
  26. implementation
  27.  
  28. const
  29.   BuffSize = 8192;
  30.   YInc : Array[1..6] of Byte = (8,8,4,2,1,0);
  31.   YLin : Array[1..6] of Byte = (0,4,2,1,0,0);
  32.   YInt : Array[1..6] of Byte = (7,3,1,0,0,0);
  33.  
  34. type
  35.   BuffType = Array[1..$FFF1] of Byte;
  36.   BuffPtr  = ^BuffType;
  37.  
  38.   PCmt = ^CmtLine;
  39.   CmtLine =
  40.     object(DoubleListNode)
  41.       Line : String[80];
  42.     end;
  43.  
  44. var
  45.   GIFBuff  : BuffPtr;
  46.   GRec     : JumpRecord;
  47.   Pass     : Byte;
  48.   Intrlace : Boolean;
  49.   Image    : Word;
  50.   Done     : Boolean;
  51.   GIFCap   : Boolean;
  52.   BufIdx   : Word;
  53.   Count    : Word;
  54.   EOFin    : Boolean;
  55.   SigOK    : Boolean;
  56.   CmtList  : DoubleList;
  57.  
  58. {-------------------------------}
  59. { High-level online GIF decoder }
  60. {-------------------------------}
  61.  
  62. procedure RingBell;
  63.   {-make a noise}
  64. begin
  65.   Sound(440);
  66.   Delay(100);
  67.   NoSound;
  68. end;
  69.  
  70. function CheckKey : Boolean;
  71.   {-return True if abort is requested via pressing <ESC>}
  72. begin
  73.   if (KeyPressed) and (ReadKey = #27) then
  74.     CheckKey := True
  75.   else
  76.     CheckKey := False;
  77. end;
  78.  
  79. procedure EndIt(B : Boolean);
  80.   {-abort the decode process}
  81. begin
  82.   if GraphOn then
  83.     SetTextMode;
  84.   if B then begin
  85.     RingBell;
  86.     RingBell;
  87.   end;
  88.   LongJump(GRec,1);
  89. end;
  90.  
  91. function FileGetByte : Byte;
  92.   {-our decoder's GetByte function}
  93. var
  94.   B : Byte;
  95. begin
  96.   if BufIdx > Count then begin
  97.     BlockRead(GifFile, GifBuff^, BuffSize, Count);
  98.     BufIdx := 1;
  99.   end;
  100.   FileGetByte := GifBuff^[BufIdx];
  101.   Inc(BufIdx);
  102. end;
  103.  
  104. procedure MyPutLine;
  105.   {-our decoder's PutLine proc.  This method accomodates interlaced GIFs}
  106. var I : Integer;
  107. begin
  108.   if CheckKey then
  109.     EndIt(False);
  110.   if YCord <= Raster then        {don't wrap back to top of screen!}
  111.     PlotLine(YCord);
  112.   Inc(YCord,YInc[Pass]);
  113.   if YCord >= BotEdge then begin
  114.     if Pass < 5 then Inc(Pass);
  115.     YCord := YLin[Pass] + TopEdge;
  116.   end;
  117. end;
  118.  
  119. procedure MyPutLineDbl;
  120.   {-our decoder's PutLine proc.  This method accomodates interlaced GIFs}
  121. var I : Integer;
  122. begin
  123.   if CheckKey then
  124.     EndIt(False);
  125.   if YCord <= Raster then        {don't wrap back to top of screen!}
  126.     PlotLine(YCord);
  127.   Inc(YCord,YInc[Pass] shl 1);
  128.   if YCord >= BotEdge then begin
  129.     if Pass < 5 then Inc(Pass);
  130.     YCord := (YLin[Pass] shl 1) + TopEdge;
  131.   end;
  132. end;
  133.  
  134. procedure AdjustVars;
  135.   {-match decode/display vars to image sizes}
  136. var I : Byte;
  137. begin
  138.   Inc(Image);
  139.   Pass := 5;
  140.   IntrLace := FALSE;
  141.   LeftEdge  := ImageLeft;
  142.   TopEdge   := ImageTop;
  143.   if (ScrWidth = 300) and (ScrHeight = 200) then begin
  144.     Inc(LeftEdge, 10);
  145.     RightEdge := ImageWidth + LeftEdge;
  146.     BotEdge   := ImageHeight + TopEdge;
  147.   end
  148.   else if (ScrWidth = 378) and (ScrHeight = 240) then begin
  149.     if (DoDbl) then begin
  150.       RightEdge := 700;
  151.       BotEdge := 480;
  152.     end
  153.     else begin
  154.       Inc(LeftEdge, 131);
  155.       Inc(TopEdge, (Raster shr 1) - 120);
  156.       RightEdge := ImageWidth + LeftEdge;
  157.       BotEdge   := ImageHeight + TopEdge;
  158.     end;
  159.   end
  160.   else begin
  161.     if ImageWidth < Pixels then
  162.       Inc(LeftEdge, (Pixels shr 1) - (ImageWidth shr 1));
  163.     if ImageHeight < Raster then
  164.       Inc(TopEdge, (Raster shr 1) - (ImageHeight shr 1));
  165.     RightEdge := ImageWidth + LeftEdge;
  166.     BotEdge   := ImageHeight + TopEdge;
  167.   end;
  168.   YCord := TopEdge;
  169.   if Maps[Local].Interlaced then
  170.     Pass := 1;
  171. end;
  172.  
  173. procedure LoadComments;
  174. var
  175.   Blk : GifBlockType;
  176.   P : PCmt;
  177.   S : String;
  178.   I : Integer;
  179. begin
  180.   S := '';
  181.   while GetExtendBlock(Blk) do begin
  182.     for I := 1 to Blk[0] do
  183.       case Chr(Blk[i]) of
  184.         #13:
  185.           begin
  186.             New(P, Init);
  187.             if P <> nil then begin
  188.               P^.Line := S;
  189.               CmtList.Append(P);
  190.             end;
  191.             S := '';
  192.           end;
  193.         #0..#31:
  194.           ;
  195.         else
  196.           S := S + Chr(Blk[i]);
  197.       end;
  198.   end;
  199. end;
  200.  
  201. procedure ShowComments;
  202. var
  203.   P : PCmt;
  204.   W : Word;
  205.   C : Char absolute W;
  206. begin
  207.   ClrScr;
  208.   P := PCmt(CmtList.Head);
  209.   while P <> nil do begin
  210.     WriteLn(P^.Line);
  211.     P := PCmt(P^.dlNext);
  212.   end;
  213.   repeat
  214.     W := ReadKeyOrButton;
  215.   until (C = #13) or (C = #27) or (Hi(W) in [$ED,$EE,$EF]);
  216. end;
  217.  
  218. function DecodeGIFFile : Integer;
  219.   {-lowlevel GIF decode routine}
  220. var I         : Integer;
  221.     BlockType : Char;
  222.     Blk       : GifBlockType;
  223.     ExtFunc   : Byte;
  224. begin
  225.     {init vars}
  226.   Done := False;
  227.   Image := 0;
  228.   CurMap := Global;
  229.   DecodeGIFFile := -9;
  230.  
  231.     {verify signature.  To accomodate future versions, we accept anything}
  232.     {with the first 3 chars "GIF" and the next 3 as 2 digits and a lower }
  233.     {case char.                                                          }
  234.   GetGIFSig;
  235.   if (Pos('GIF',GIFSig) <> 1) or
  236.      (NOT(GIFSig[4] in ['0'..'9'])) or
  237.      (NOT(GIFSig[5] in ['0'..'9'])) or
  238.      (NOT(GIFSig[6] in ['a'..'z'])) then begin
  239. {$IFDEF Debug}
  240.     WriteLn('Failed decoding signature '+GIFSig);
  241. {$ENDIF}
  242.     Sound(440);
  243.     Delay(100);
  244.     NoSound;
  245.     delay(2000);
  246.     EndIt(False);
  247.   end;
  248.  
  249.     {get the hardware specifics, match a video mode as close as we can}
  250.   GetScrDes(Maps[CurMap]);
  251.  
  252.   SelMode := SelectMode(ScrWidth,ScrHeight);
  253.   if SelMode = 0 then EndIt(True);
  254.  
  255.     {if we have a global map, process it}
  256.   if Maps[Global].MapExists then
  257.     DoMapping
  258.   else
  259.     SetDefMap;
  260.  
  261.     {kick into graphics mode then juggle the palette to match our map}
  262.   if (CurrentDisplay in [EGA,VGA]) and
  263.      (ScrWidth = 378) and
  264.      (ScrHeight = 240) then
  265.     if DoDbl then
  266.       PutLine := MyPutLineDbl;
  267.   SetGraphicsMode(SelMode);
  268.   AdjustPalette(SelMode);
  269.  
  270.     {loop reading blocks and processing...}
  271.   while NOT Done do begin
  272.     BlockType := Chr(GetByte);
  273.     case BlockType of
  274.       ',': begin                             {"Local descriptor", process...}
  275.              GetImageDescription(Maps[Local]);
  276.              AdjustVars;
  277.              CurMap := Global;
  278.              if Maps[Local].MapExists then begin
  279.                  {juggle palette again}
  280.                CurMap := Local;
  281.                DoMapping;
  282.                AdjustPalette(SelMode);
  283.              end;
  284.                {decode the image data and display}
  285.              I := ExpandGIF;
  286.              if I <> 0 then begin
  287.                DecodeGIFFile := I;
  288.                EndIt(True);
  289.              end;
  290.            end;
  291.       '!': begin                                  {"Extension" block...}
  292.              ExtFunc := GetExtendFunc;            {get the function type}
  293.              case ExtFunc of
  294.                $FE:
  295.                  LoadComments;                    {load comments for later}
  296.                else
  297.                  while GetExtendBlock(Blk) do ;   {discard the block}
  298.              end;
  299.            end;
  300.       ';': begin                {Terminator seen, clean up and go home}
  301.              Done := True;
  302.              DecodeGIFFile := 0;
  303.              exit;
  304.            end;
  305.     end;
  306.   end;
  307. end;
  308.  
  309. function DisplayGIFOffLine(FN : String) : Boolean;
  310.   {-display a GIF file onscreen}
  311. var L : LongInt;
  312.     W : Word;
  313.     C : Char Absolute W;
  314.     N : Integer;
  315. begin
  316.   DisplayGIFOffLine := False;
  317.  
  318.     {point to our routines}
  319.   GetByte := FileGetByte;
  320.   PutLine := MyPutLine;
  321.   if NOT GetMemCheck(GIFBuff,BuffSize) then exit;
  322.   CmtList.Init;
  323.  
  324.     {init error handler}
  325.   N := SetJump(GRec);
  326.   if N <> 0 then begin
  327.     Close(GifFile);
  328.     if IOResult = 0 then ;
  329.     CmtList.Done;
  330.     FreeMemCheck(GIFBuff, BuffSize);
  331.     exit;
  332.   end;
  333.  
  334.     {init capture file}
  335.   Count := 0;
  336.   BufIdx := 999;
  337.   Assign(GifFile, FN);
  338.   Reset(GifFile, 1);
  339.   if IOResult <> 0 then begin
  340.     CmtList.Done;
  341.     FreeMemCheck(GIFBuff, BuffSize);
  342.     exit;
  343.   end;
  344.  
  345.     {process...}
  346.   N := DecodeGIFFile;
  347.  
  348.   if N = 0 then begin
  349.     RingBell;
  350.     DisplayGIFOffline := True;
  351.       {wait for <CR> or <ESC> before clearing}
  352.     repeat
  353.       W := ReadKeyOrButton;
  354.     until (C = #13) or (C = #27) or (Hi(W) in [$ED,$EE,$EF]);
  355.     ClearMouseEvents;
  356.     SetTextMode;
  357.     Close(GifFile);  if IOResult = 0 then ;
  358.  
  359.     if CmtList.Size <> 0 then
  360.       ShowComments;
  361.   end;
  362.  
  363.   CmtList.Done;
  364.   FreeMemCheck(GIFBuff, BuffSize);
  365. end;
  366.  
  367. end.
  368.